package com.xcity.tools.template;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class BuildConvert {

	public static void main(String[] args) throws Exception {
	
		File parent = new File("F:/prj_java/city_doc/策划/配置表");
		
		Workbook wb = getWorkbook(new File(parent, "Deprecated/build.xlsx"));
		Sheet sheet = wb.getSheetAt(0);
		int from = 3;//sheet.getFirstRowNum();
		int to = sheet.getLastRowNum();
		List<Build> buildList = new ArrayList<>();
		for (int i = from; i <= to; i++) {
			Row row = sheet.getRow(i);
			int rf = row.getFirstCellNum();
			int rt = row.getLastCellNum();
			Build build = new Build();
			int buyPrice = 0;
			for (int j = rf; j < rt; j++) {
				Cell cell = row.getCell(j);
				if (cell == null) {
					break;
				}
				Object value;
				switch (cell.getCellType()) {
//				case Cell.CELL_TYPE_BLANK:
					case Cell.CELL_TYPE_NUMERIC:
						value = cell.getNumericCellValue();
						break;
					case Cell.CELL_TYPE_STRING:
						value = cell.getStringCellValue();
						break;
//				case Cell.CELL_TYPE_FORMULA:
					case Cell.CELL_TYPE_BOOLEAN:
						value = cell.getBooleanCellValue();
						break;
//				case Cell.CELL_TYPE_ERROR:
					default:
						value = "";
				}
				
				if (j == 0) { // id
				} else if (j == 1) { // buildId
					build.id = ((Number) value).intValue();
				} else if (j == 2) { // name
					build.name = value.toString().trim();
				} else if (j == 3) { // img
					build.image = value.toString().trim();
				} else if (j == 4) { // cost
					build.unlockPrice = ((Number) value).longValue();
				} else if (j == 5) { // type
					build.type = ((Number) value).byteValue();
				} else if (j == 6) { // buyType
					build.costType = ((Number) value).byteValue();
				} else if (j == 7) { // buyPrice
					buyPrice = ((Number) value).intValue();
				} else if (j == 8) { // desc
					build.desc = value.toString().trim();
				} else { // lv1-20
//					建筑CD|升级消耗|收益|最大收益|风险值|出售价格|分级经验
					if (value.toString().trim().isEmpty()) {
						break;
					}
					String[] vals = value.toString().trim().split("\\|");
					BuildLevelUp lvlup = new BuildLevelUp();
					build.levelUpSettings.add(lvlup);
//					int level, int cd, int cost, int income, int maxIncome, int risk, int price, int exp
					lvlup.buildId = build.id;
					lvlup.level = build.levelUpSettings.size();
					lvlup.cd = (int) (Double.parseDouble(vals[0]) / 1000);
					lvlup.cost = lvlup.level == 1 ? buyPrice : Double.valueOf(vals[1]).intValue();
					lvlup.income = Double.valueOf(vals[2]).intValue();
					lvlup.maxIncome = Double.valueOf(vals[3]).intValue();
					lvlup.risk = Double.valueOf(vals[4]).intValue();
					lvlup.price = Double.valueOf(vals[5]).intValue();
					lvlup.exp = Double.valueOf(vals[6]).intValue();
				}
			}
			buildList.add(build);
		}
		wb.close();
		
		buildList.sort(new Comparator<Build>() {
			@Override
			public int compare(Build b1, Build b2) {
				return b1.id - b2.id;
			}
		});
		
		
		wb = new XSSFWorkbook();
		sheet = wb.createSheet("建筑列表");
		Map<Integer, Integer> widths = new LinkedHashMap<>();
		// head
		// row0: filed name
		// row1: filed type (byte, short, int, ...)
		// row2: file comment
//		Font font = wb.createFont();
//		font.setColor(HSSFColor.BROWN.index);
//		font.setBold(true);
		CellStyle style = wb.createCellStyle();
//		style.setBorderTop(HSSFCellStyle.BORDER_HAIR);
//		style.setBorderBottom(HSSFCellStyle.BORDER_HAIR);
//	    style.setBorderLeft(HSSFCellStyle.BORDER_HAIR);
//	    style.setBorderRight(HSSFCellStyle.BORDER_HAIR);
//	    style.setFillBackgroundColor(HSSFColor.TEAL.index);
	    style.setFillForegroundColor((short) 0x45);
	    style.setFillPattern(CellStyle.SOLID_FOREGROUND);
//		style.setBottomBorderColor(HSSFColor.RED.index);
//		style.setFont(font);
		int rowOffset = 0;
		Row row = sheet.createRow(rowOffset++);
		row.setHeight((short) (1.2 * 256));
		Row row1 = sheet.createRow(rowOffset++);
		Row row2 = sheet.createRow(rowOffset++);
		Field[] fs = Build.class.getDeclaredFields();
		for (int i = 0; i < fs.length; i++) {
			Field f = fs[i];
			if (f.getName().equals("levelUpSettings")) {
				continue;
			}
			Cell cell = row.createCell(i);
//			cell.setCellStyle(style);
			cell.setCellValue(f.getName());
			fixColWidth(cell, widths);
			
			cell = row1.createCell(i);
//			cell.setCellStyle(style);
			cell.setCellValue(f.getType().getSimpleName());
			fixColWidth(cell, widths);
			
			cell = row2.createCell(i);
//			cell.setCellStyle(style);
			Comment c = f.getDeclaredAnnotation(Comment.class);
			cell.setCellValue(c != null ? c.value() : "");
			fixColWidth(cell, widths);
		}
		
		// fill data
		for (int i = 0; i < buildList.size(); i++) {
			Build build = buildList.get(i);
			row = sheet.createRow(rowOffset++);
			
			for (int j = 0; j < fs.length; j++) {
				Field f = fs[j];
				if (f.getName().equals("levelUpSettings")) {
					continue;
				}
				Class<?> clazz = f.getType();
				Cell cell = row.createCell(j);
				if (clazz == byte.class) {
					cell.setCellValue(f.getByte(build));
				} else if (clazz == int.class) {
					cell.setCellValue(f.getInt(build));
				} else if (clazz == long.class) {
					cell.setCellValue(f.getLong(build));
				} else {
					Object o = f.get(build);
					cell.setCellValue(o.toString());
				}
				fixColWidth(cell, widths);
			}
		}
		sheet.setDefaultRowHeight((short) (1.3 * 256));
		for (Entry<Integer, Integer> e : widths.entrySet()) {
			sheet.setColumnWidth(e.getKey(), e.getValue());
		}
		
		
		widths.clear();
		sheet = wb.createSheet("建筑升级配置");
		// head
		rowOffset = 0;
		Row head0 = sheet.createRow(rowOffset++);
		Row head1 = sheet.createRow(rowOffset++);
		Row head2 = sheet.createRow(rowOffset++);
		Field[] fields = BuildLevelUp.class.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field f = fields[i];
			Cell cell = head0.createCell(i);
//			cell.setCellStyle(style);
			cell.setCellValue(f.getName());
			fixColWidth(cell, widths);
			
			cell = head1.createCell(i);
//			cell.setCellStyle(style);
			cell.setCellValue(f.getType().getSimpleName());
			fixColWidth(cell, widths);
			
			cell = head2.createCell(i);
//			cell.setCellStyle(style);
			Comment c = f.getDeclaredAnnotation(Comment.class);
			cell.setCellValue(c != null ? c.value() : "");
			fixColWidth(cell, widths);
		}
		
		// level up detail
		for (int i = 0; i < buildList.size(); i++) {
			Build build = buildList.get(i);
			List<BuildLevelUp> buildLvlups = build.levelUpSettings;
			for (int j = 0; j < buildLvlups.size(); j++) {
				row = sheet.createRow(rowOffset++);
				BuildLevelUp obj = buildLvlups.get(j);
				for (int k = 0; k < fields.length; k++) {
					Field f = fields[k];
					Class<?> clazz = f.getType();
					Cell cell = row.createCell(k);
					if (clazz == byte.class) {
						cell.setCellValue(f.getByte(obj));
					} else if (clazz == int.class) {
						cell.setCellValue(f.getInt(obj));
					} else if (clazz == long.class) {
						cell.setCellValue(f.getLong(obj));
					} else {
						Object o = f.get(obj);
						cell.setCellValue(o.toString());
					}
					fixColWidth(cell, widths);
				}
			}
		}
		sheet.setDefaultRowHeight((short) (1.3 * 256));
		for (Entry<Integer, Integer> e : widths.entrySet()) {
			sheet.setColumnWidth(e.getKey(), e.getValue());
		}
		
		
		OutputStream out = new FileOutputStream(new File(parent, "build.xlsx"));
		wb.write(out);
		
		out.flush();
		out.close();
		
		wb.close();
		System.out.println("ok");
	}
	
	static void fixColWidth(Cell cell, Map<Integer, Integer> widths) {
		int index = cell.getColumnIndex();
		Integer w = widths.get(index);
		if (w == null) {
			w = 0;
		}
		String value = "";
		switch (cell.getCellType()) {
			case Cell.CELL_TYPE_NUMERIC:
				value = String.valueOf(cell.getNumericCellValue());
				break;
			case Cell.CELL_TYPE_STRING:
				value = cell.getStringCellValue();
				break;
			case Cell.CELL_TYPE_BOOLEAN:
				value = String.valueOf(cell.getBooleanCellValue());
				break;
		}
		int width = (int) (value.length() * 256 * 1.5);
		if (width > w) {
			widths.put(index, width);
		}
	}
	
	static Workbook getWorkbook(File file) throws Exception {
		if (file.getName().endsWith("xlsx")) {
			return new XSSFWorkbook(file);
		}
		return new HSSFWorkbook(new FileInputStream(file));
	}
	
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.FIELD)
	static @interface Comment {
		String value() default "";
	}
	
	static class Build {
		@Comment("建筑id")
		int id;
		@Comment("建筑名称")
		String name;
		@Comment("建筑类型(1:普通建筑; 2:未定义; 3:公益建筑)")
		byte type;
		@Comment("描述")
		String desc;
		@Comment("图片")
		String image;
		@Comment("解锁价格")
		long unlockPrice;
		@Comment("建造/升级所消耗的货币类型(1:现金; 2:钻石)")
		byte costType;
		List<BuildLevelUp> levelUpSettings = new ArrayList<>();
		Build() {}
		Build(int id, String name, byte type, String desc, String image, long unlockPrice, byte costType) {
			this.id = id;
			this.name = name;
			this.type = type;
			this.desc = desc;
			this.image = image;
			this.unlockPrice = unlockPrice;
			this.costType = costType;
		}
	}
	
	static class BuildLevelUp {
		@Comment("建筑id")
		int buildId;
		@Comment("等级")
		int level;
		@Comment("建造cd(秒)")
		int cd;
		@Comment("消耗货币数量")
		int cost;
		@Comment("每分钟收益")
		int income;
		@Comment("最大收益")
		int maxIncome;
		@Comment("风险值")
		int risk;
		@Comment("出售价格(现金)")
		int price;
		@Comment("建造完成可获得的经验")
		int exp;
		BuildLevelUp() {}
		BuildLevelUp(int level, int cd, int cost, int income, int maxIncome, int risk, int price, int exp) {
			this.level = level;
			this.cd = cd;
			this.cost = cost;
			this.income = income;
			this.maxIncome = maxIncome;
			this.risk = risk;
			this.price = price;
			this.exp = exp;
		}
	}
	
	
	
}
